package com.ysw.rpc.client.interceptor;

import com.ysw.rpc.client.utils.ChannelUtil;
import com.ysw.rpc.common.messages.Request;
import com.ysw.rpc.common.messages.Response;
import com.ysw.rpc.common.utils.IdUtil;
import io.netty.util.concurrent.Promise;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import org.springframework.util.StringUtils;

import java.lang.reflect.Method;

/**
 * @author YinShangwen
 * @since 2023/4/18 11:23
 */
public class ProxyMethodInterceptor implements MethodInterceptor {
    public final Class<?> clazz;

    public ProxyMethodInterceptor(Class<?> clazz) {
        this.clazz = clazz;
    }

    public Object getInstance() {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);
        return enhancer.create();
    }

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        Request request = new Request();
        request.setId(IdUtil.generateId());
        request.setParameterTypes(method.getParameterTypes());
        request.setArgs(args);
        request.setReferenceClassName(clazz.getName());
        request.setMethodName(method.getName());

        Promise<Response> promise = ChannelUtil.sendMsg(request, clazz);

        Response response = promise.get();
        if (StringUtils.hasText(response.getError())) {
            throw new RuntimeException(response.getError());
        }
        return response.getResult();
    }
}
